#include "genie_sal.h"
#include "genie_mesh_api.h"

#include "sensor_input.h"
#include "sensor_led.h"
#include "sensor_queue.h"
#include "sensor_factory.h"

static sensor_factory_t sensor_factory;

static void sensor_factory_response(const char *response)
{
    aos_cli_printf("%s%s\r\n", PREFIX_RESPONSE_CLI, response);
}

static void factory_handle(char *pwbuf, int blen, int argc, char **argv)
{
    if (!strncmp(argv[1], "start", 5))
    {
        sensor_factory.is_in_facotry = 1;
    }
    else if (!strncmp(argv[1], "stop", 4))
    {
        sensor_factory.is_in_facotry = 0;
    }
}

static void power_handle(char *pwbuf, int blen, int argc, char **argv)
{
    int ret = 0;

    if (sensor_factory.is_in_facotry == 0)
    {
        sensor_factory_response("not factory mode");
        return;
    }

    if (!strncmp(argv[1], "down", 4))
    {
        ret = genie_mesh_suspend(true);
        if (ret == 0)
        {
            //enableSleepInPM(0xFF);
            sensor_factory_response("ok");
        }
        else
        {
            sensor_factory_response("fail");
        }
    }
    else if (!strncmp(argv[1], "up", 2))
    {
        ret = genie_mesh_resume();
        if (ret == 0)
        {
            //disableSleepInPM(0xFF);
            sensor_factory_response("ok");
        }
        else
        {
            sensor_factory_response("fail");
        }
    }
}

static void auto_send_timer_cb(void *timer, void *arg)
{
    queue_mesg_t mesg;

    memset(&mesg, 0, sizeof(queue_mesg_t));
    mesg.type = QUEUE_MESG_TYPE_INPUT;
    mesg.data = (uint32_t)SWITCH_PRESS_ONCE;

    queue_send_data(&mesg);
}

static void switch_handle(char *pwbuf, int blen, int argc, char **argv)
{
    uint32_t send_timeout = 0;

    if (sensor_factory.is_in_facotry == 0)
    {
        sensor_factory_response("not factory mode");
        return;
    }

    if (!strncmp(argv[1], "start", 5))
    {
        sensor_factory.is_switch_testing = 1;
    }
    else if (!strncmp(argv[1], "stop", 4))
    {
        sensor_factory.is_switch_testing = 0;
    }
    else if (!strncmp(argv[1], "send", 4))
    {
        send_timeout = atoi(argv[2]);
        if (send_timeout > 0)
        {
            if (sensor_factory.auto_send_timer.hdl == NULL)
            {
                aos_timer_new(&sensor_factory.auto_send_timer, auto_send_timer_cb, NULL, send_timeout * 1000, 1);
            }
            else
            {
                aos_timer_stop(&sensor_factory.auto_send_timer);
                aos_timer_change(&sensor_factory.auto_send_timer, send_timeout * 1000);
            }

            sensor_factory.is_in_facotry = 0; //allow sleep
            aos_timer_start(&sensor_factory.auto_send_timer);
        }
    }
}

static void led_handle(char *pwbuf, int blen, int argc, char **argv)
{
    if (sensor_factory.is_in_facotry == 0)
    {
        sensor_factory_response("not factory mode");
        return;
    }

    if (!strncmp(argv[1], "on", 2))
    {
        if (0 == sensor_set_led_status(LED_ON))
        {
            sensor_factory_response("ok");
        }
        else
        {
            sensor_factory_response("fail");
        }
    }
    else if (!strncmp(argv[1], "off", 3))
    {
        if (0 == sensor_set_led_status(LED_OFF))
        {
            sensor_factory_response("ok");
        }
        else
        {
            sensor_factory_response("fail");
        }
    }
}

static void appver_handle(char *pwbuf, int blen, int argc, char **argv)
{
    char appver[16];

    if (sensor_factory.is_in_facotry == 0)
    {
        sensor_factory_response("not factory mode");
        return;
    }

    if (!strncmp(argv[1], "get", 3))
    {
        memset(appver, 0, sizeof(appver));
        genie_version_appver_string_get(appver, 16);
        sensor_factory_response(appver);
    }
    else
    {
        sensor_factory_response("fail");
    }
}

static int _set_triple(char *pid_in, char *key_in, char *mac_in)
{
    uint8_t ret;
    uint32_t pid;
    uint8_t key[16];
    uint8_t mac[MAC_LEN], read_mac[MAC_LEN];

    pid = atol(pid_in);
    if (pid == 0)
    {
        GENIE_LOG_ERR("pid err");
        return -1;
    }

    if (strlen(key_in) != 32)
    {
        GENIE_LOG_ERR("key len err");
        return -1;
    }
    ret = stringtohex(key_in, key, 16);
    if (ret == 0)
    {
        GENIE_LOG_ERR("key format err");
        return -1;
    }

    if (strlen(mac_in) != 12)
    {
        GENIE_LOG_ERR("mac len err");
        return -1;
    }
    ret = stringtohex(mac_in, mac, MAC_LEN);
    if (ret == 0)
    {
        GENIE_LOG_ERR("mac format err");
        return -1;
    }

    hal_flash_write_mac_params(mac, MAC_LEN);
    memset(read_mac, 0xFF, MAC_LEN);
    hal_flash_read_mac_params(read_mac, MAC_LEN);
    if (memcmp(mac, read_mac, MAC_LEN))
    {
        GENIE_LOG_ERR("write mac fail");
        return -1;
    }

    ret = genie_triple_write(&pid, mac, key);

    return ret;
}

static void triple_handle(char *pwbuf, int blen, int argc, char **argv)
{
    genie_storage_status_e ret;
    uint32_t pid;
    uint8_t mac[6];
    char mac_str[13];
    uint8_t key[16];
    char key_str[33];
    char triple[64];

    if (sensor_factory.is_in_facotry == 0)
    {
        sensor_factory_response("not factory mode");
        return;
    }

    if (!strncmp(argv[1], "set", 3))
    {
        if (0 != _set_triple(argv[2], argv[3], argv[4]))
        {
            sensor_factory_response("fail");
        }
        else
        {
            sensor_factory_response("ok");
        }
    }
    else if (!strncmp(argv[1], "get", 3))
    {
        ret = genie_triple_read(&pid, mac, key);
        if (ret != GENIE_STORAGE_SUCCESS)
        {
            sensor_factory_response("fail");
        }
        else
        {
            memset(triple, 0, sizeof(triple));
            memset(key_str, 0, sizeof(key_str));
            memset(mac_str, 0, sizeof(mac_str));

            hextostring(mac, mac_str, 6);
            hextostring(key, key_str, 16);

            snprintf(triple, sizeof(triple), "[%u,%s,%s]", pid, key_str, mac_str);
            sensor_factory_response(triple);
        }
    }
}

static const struct cli_command sensor_factory_cmds[] = {
    {"factory", "factory start|factory stop", factory_handle},
    {"power", "power down|power up", power_handle},
    {"led", "led on|led off", led_handle},
    {"switch", "switch start|switch stop", switch_handle},
    {"triple", "triple set pid key mac|triple get", triple_handle},
    {"appver", "appver get", appver_handle},
};

int sensor_factory_handle_switch(switch_press_type_e press_type)
{
    if (sensor_factory.is_in_facotry == 1 && sensor_factory.is_switch_testing == 1)
    {
        if (press_type == SWITCH_PRESS_PRESSED)
        {
            sensor_factory_response("pressed");
        }
        else if (press_type == SWITCH_PRESS_RELEASED)
        {
            sensor_factory_response("released");
        }

        return 1;
    }

    return 0;
}

int sensor_factory_is_factory_mode(void)
{
    return sensor_factory.is_in_facotry;
}

void sensor_factory_init(void)
{
    memset(&sensor_factory, 0, sizeof(sensor_factory_t));

#ifdef CONFIG_AOS_CLI
    aos_cli_register_commands(&sensor_factory_cmds[0], sizeof(sensor_factory_cmds) / sizeof(sensor_factory_cmds[0]));
#endif
}
